﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using App.Core.Extensions;
using App.Domain;
using App.Web.ViewModels;
using App.Web.Utility;
using AutoMapper;
using System.Data;
using App.Search;
using App.Web.ViewModels.UtilityModels;
//using Lucene.Net.Index;
//using Lucene.Net.Search;

namespace App.Web.Controllers
{
    public class ProductController : BaseController
    {
        private EntityRepository _Repository = new EntityRepository();
        private AppEntities _Context = new AppEntities();

        #region Constructor

        public ProductController()
		{
		}

		public ProductController(UserViewModel currentUser)
			: base(currentUser)
        {
        }

        #endregion Constructor

        #region Action Methods

        public ActionResult Index()
        {
            return RedirectToAction("Search");
        }

        /// <summary>
        /// Gets the Necessary Information to Display a Product Details
        /// </summary>
        /// <param name="id"></param>
        /// <param name="name"></param>
        /// <returns></returns>
        public ActionResult Details(int id = 0, String productKey = null, String companyKey = null)
        {
            ProductViewModel product = null;
            Product entity = _Repository.GetProductByID(id);
            if (entity != null)
            {
                ///Check if this is correct URL, otherwise redirect to the correct Product URL 
                ///with the HTTP Status code 301 (Moved Permanently) 
                ///This redirection has been removed for the non english character in URL.
                //if (String.Compare(entity.ProductUrl, productKey, true) != 0)
                //{
                //    return RedirectToRoutePermanent(AppConstants.RouteNames.Public.ITEM_DETAILS, new { id = id, productKey = entity.ProductUrl });
                //}

                UtilityDAO dao = new UtilityDAO();
                DbParameter[] parameters = new[]{
                    new DbParameter("@ProductID", entity.ID),
                    new DbParameter("@CategoryID", entity.CategoryID),
                    new DbParameter("@RecordToReturn", 5)
                };

                System.Data.DataSet topViewedProducts = dao.GetDataSet(DbObject.SP.GET_SIMILAR_PRODUCTS, parameters, true);
                ViewData[AppConstants.ViewDataKeys.TOP_VIEWED_PRODUCTS] = topViewedProducts;
                //ViewData[AppConstants.ViewDataKeys.COMPANY_KEY] = company.CompnayUrl;

                ///Update Product Visit 
                String sessionKey = WebUtil.GetSessionKey();
                ProductVisitDetail productVisitDetail = _Context.ProductVisitDetails.FirstOrDefault(P => P.ProductID == id && P.SessionKey.ToLower() == sessionKey.ToLower());
                if (productVisitDetail == null)
                {
                    productVisitDetail = new ProductVisitDetail();
                    productVisitDetail.ProductID = id;
                    productVisitDetail.VisitedDate = System.DateTime.Now;
                    productVisitDetail.SessionKey = sessionKey;
                    productVisitDetail.ClientIP = WebUtil.GetRemoteIPAddress();
                    productVisitDetail.BrowserName = String.Format("{0} {1}", Request.Browser.Browser, Request.Browser.Version);
                    _Context.AddToProductVisitDetails(productVisitDetail);
                    bool isOwnUser = false;
                    if (LoggedInUser != null)
                    {
                        if (LoggedInUser.Company != null && LoggedInUser.Company.ID == entity.CompanyID)
                            isOwnUser = true;
                        else
                            productVisitDetail.UserId = LoggedInUser.ID;                        
                    }
                    if(!isOwnUser)
                        _Context.SaveChanges();
                }
                //End saving

                product = Mapper.Map<ProductViewModel>(entity);
                WebUtil.MapZGL(product, entity.Category.PropertyDefinition);
            }
            return View(product);
        }

        #region Obsolete Lucene Search Codes
        //public ActionResult Search(String keyword = "Tutul")
        //{
        //    String path = LuceneEngine.LuceneIndexDirectory;
        //    #region Old Implementation
        //    Lucene.Net.QueryParsers.QueryParser parser = new Lucene.Net.QueryParsers.QueryParser("Name", LuceneEngine._Analyzer);
        //    Lucene.Net.Search.Query query = null;
        //    Lucene.Net.Search.Searcher searcher = null;
        //    try
        //    {
        //        if (string.IsNullOrEmpty(keyword))
        //        {
        //            throw new Exception("You forgot to enter something to search for...");
        //        }

        //        query = parser.Parse(keyword);

        //    }
        //    catch (Exception ex)
        //    {
        //        Console.WriteLine(ex.Message);
        //    }


        //    //lock (my_lock)
        //    //{

        //    Lucene.Net.Search.Hits hits = null;
        //    try
        //    {
        //        if (searcher == null)
        //        {
        //            searcher = new Lucene.Net.Search.IndexSearcher(path);
        //        }
        //        hits = searcher.Search(query);
        //    }
        //    catch (Exception ex)
        //    {
        //        Console.WriteLine(ex.Message);
        //    }
        //    #endregion Old Implementation
        //    //IndexReader reader = IndexReader.Open(LuceneEngine.LuceneIndexDirectory);
        //    //Searcher searcher = new IndexSearcher(reader);

        //    //BooleanQuery booleanQuery = new BooleanQuery();
        //    //Query query1 = new TermQuery(new Term("Description", keyword));
        //    //Query query2 = new TermQuery(new Term("Name", keyword));
        //    //if (keyword.Contains(' '))
        //    //{
        //    //    //PhraseQuery q1 = new PhraseQuery("A Level");
        //    //    //booleanQuery.Add(new PhraseQuery());
        //    //}
        //    //booleanQuery.Add(query1, BooleanClause.Occur.SHOULD);
        //    //booleanQuery.Add(query2, BooleanClause.Occur.SHOULD);
        //    //// Use BooleanClause.Occur.MUST instead of BooleanClause.Occur.SHOULD
        //    //// for AND queries
        //    //Hits hits = searcher.Search(booleanQuery);

        //    for (int i = 0; i < hits.Length(); i++)
        //    {
        //        Lucene.Net.Documents.Document doc = hits.Doc(i);
        //        //~~
        //        //~~ more processing of the hits and the Lucene docs here ~~
        //        //~~
        //    }
        //    //}
        //    return View();
        //}
        #endregion Obsolete Lucene Search Codes

        #region Obsolete Codes
        ///// <summary>
        ///// Get List Of Product Added To Wish List
        ///// </summary>
        ///// <param name="id"></param>
        ///// <param name="name"></param>
        ///// <returns></returns>
        //public ActionResult WishList(String id)
        //{
        //    int pageNo = id.ToInt() > 0 ? id.ToInt() : 1;
        //    int pageSize = ConfigReader.pageSize;

        //    UtilityDAO dao = new UtilityDAO();
        //    DbParameter[] parameters = new[] { 
        //    //new DbParameter("@CompanyID", 1), 
        //    //new DbParameter("@SearchKey", SearchKey),
        //    new DbParameter("@UserId",(SessionCache.CurrentUser==null)? 0 : SessionCache.CurrentUser.ID),
        //    };
        //    int totalRecord = 0;
        //    System.Data.DataSet ds =
        //        dao.GetPagedData(        DbObject.SP.GET_PRODUCT_FROM_WISH_LIST,
        //        parameters, pageNo, pageSize, out totalRecord, true);
        //    ViewBag.PageNumber = pageNo;
        //    ViewBag.PageSize = pageSize;
        //    ViewBag.TotalRecord = totalRecord;
        //    ViewBag.DataSource = ds;
        //    ViewBag.SearchType = "WishList";
        //    //ViewBag.ShowEditLink = true;

        //    ViewModels.UtilityModels.PagerConfig pagerConfig = new ViewModels.UtilityModels.PagerConfig();
        //    pagerConfig.PageNo = pageNo;
        //    pagerConfig.PageSize = pageSize;
        //    //pagerConfig.TotalRecordMessage = "Total {0} Products Found";


        //    pagerConfig.UrlFormat = "/Product/WishList?id={0}";

        //    ViewBag.PagerConfig = pagerConfig;
        //    ViewBag.TotalRecord = pagerConfig.TotalRecord = totalRecord;

        //    return View();
        //}

        /// <summary>
        /// Depricated by Lucene Search
        /// </summary>
        /// <param name="id"></param>
        /// <param name="Key"></param>
        /// <returns></returns>
        //public ActionResult Search(String id, String Key = "")
        //{

        //    int pageNo = id.ToInt() > 0 ? id.ToInt() : 1;
        //    int pageSize = ConfigReader.pageSize;

        //    UtilityDAO dao = new UtilityDAO();
        //    DbParameter[] parameters = new[] { 
        //    new DbParameter("@CompanyID", 1), 
        //    new DbParameter("@SearchKey", Key),
        //    new DbParameter("@UserID",(SessionCache.CurrentUser==null)? 0 : SessionCache.CurrentUser.ID),
        //    };
        //    int totalRecord = 0;
        //    System.Data.DataSet ds =
        //        dao.GetPagedData((Key == "Pupular Search") ? DbObject.SP.GET_PRODUCT_POPULAR_SEARCH :
        //        (Key == "Discount Products") ? DbObject.SP.GET_PRODUCT_BY_DISCOUNT_PRODUCTS :
        //        (Key == "Special Offer") ? DbObject.SP.GET_PRODUCT_BY_SPECIAL_OFFERS :
        //        DbObject.SP.GET_PRODUCT_BY_SEARCH
        //        ,
        //        parameters, pageNo, pageSize, out totalRecord, true);
        //    ViewBag.PageNumber = pageNo;
        //    ViewBag.PageSize = pageSize;
        //    ViewBag.TotalRecord = totalRecord;
        //    ViewBag.DataSource = ds;
        //    ViewBag.SearchType = Key;
        //    //ViewBag.ShowEditLink = true;

        //    ViewModels.UtilityModels.PagerConfig pagerConfig = new ViewModels.UtilityModels.PagerConfig();
        //    pagerConfig.PageNo = pageNo;
        //    pagerConfig.PageSize = pageSize;
        //    //pagerConfig.TotalRecordMessage = "Total {0} Products Found";


        //    pagerConfig.UrlFormat = (Key == "Pupular Search") ? "/Search/View?id={0}&SearchKey=Pupular Search" :
        //        (Key == "Discount Products") ? "/Search/View?id={0}&SearchKey=Discount Products" :
        //        (Key == "Special Offer") ? "/Search/View?id={0}&SearchKey=Special Offer" :
        //        "/Search/View?id={0}";

        //    ViewBag.PagerConfig = pagerConfig;
        //    ViewBag.TotalRecord = pagerConfig.TotalRecord = totalRecord;

        //    return View();
        //}
        #endregion

        /// <summary>
        /// Deals with product comparison. Product IDs should be given as Comma(,) separed.
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public ActionResult Compare(String id)
        {
            if (id.IsEmpty())
                return View();
            else
            {
                List<int> productIDs = getProductIDCollection(id);
                if (productIDs.Contains(0))  ///Somehow User Tempered the URL with invalid values                
                    return View();

                List<Product> entities = _Repository.GetProductByID(productIDs.ToArray());
                List<ProductViewModel> products = Mapper.Map<List<ProductViewModel>>(entities);

                ///MAP LGL Properties
                for (int i = 0; i < products.Count; i++)
                {
                    ProductViewModel product = products[i];
                    Product entity = entities[i];
                    WebUtil.MapZGL(product, entity.Category.PropertyDefinition);

                }

                int LoggedInUserID = (LoggedInUser == null) ? 0 : LoggedInUser.ID;

                var query = from P in _Context.UserWishLists
                            where productIDs.Contains(P.ProductID)
                            && P.UserID == LoggedInUserID
                            && P.IsActive == true
                            select P.ProductID;
                List<int> productsInWishList = new List<int>();

                if (query != null && query.Count() > 0)
                    productsInWishList = query.ToList();
                ViewBag.ProductInWishList = productsInWishList;


                return View(products);
            }

            //if (LoggedInUser == null)
            //{
            //    ViewBag.LogOnMessage = "Sorry! You are not logged on.";
            //    return RedirectToAction("LogOn","Account");
            //}
            //else
            //{
                
            //}
        }

        private List<int> getProductIDCollection(string ids)
        {
            String[] strIDs = ids.Split(',');
            List<int> productIDs = new List<int>();
            foreach (String str in strIDs)
            {
                productIDs.Add(str.ToInt());
            }
            return productIDs;
        }
        /// <summary>
        /// Lists product by category
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public ActionResult Category(String id, String pageNo)
        {            
            //Category entity = _Context.Categories.FirstOrDefault(P => String.Compare(P.UrlName, id, true) == 0);
            CategoryViewModel category = ApplicationCache.Categories.FirstOrDefault(C => String.Compare(C.UrlName, id, true) == 0); //Mapper.Map<Category, CategoryViewModel>(entity);
            if (category != null)
            {
                System.Text.StringBuilder sb = new System.Text.StringBuilder(10);
                if (category.ChildCategories.Count > 0)
                {
                    foreach (var childCategory in category.ChildCategories)
                    {
                        if (childCategory.ChildCategories.Count > 0)
                        {
                            foreach (var childCategory2 in childCategory.ChildCategories)
                            {
                                if (sb.Length == 0)
                                    sb.Append(childCategory2.ID);
                                else
                                    sb.AppendFormat(",{0}", childCategory2.ID);
                            }
                        }
                        else
                        {

                            if (sb.Length == 0)
                                sb.Append(childCategory.ID);
                            else
                                sb.AppendFormat(",{0}", childCategory.ID);
                        }
                    }
                }
                else
                    sb.Append(category.ID);
                UtilityDAO dao = new UtilityDAO();

                DbParameter[] parameters =
                    new[] { 
                        new DbParameter("@CategoryIDs", sb.ToString()),
                        new DbParameter("@UserID", SessionCache.CurrentUser == null ? 0 : SessionCache.CurrentUser.ID) 
                };

                /*
                DbParameter[] parameters = new[] { 
                    new DbParameter("@CategoryIDs", sb.ToString(),
                    new DbParameter("@UserID", SessionCache.CurrentUser == null ? 0 : SessionCache.CurrentUser.ID
                    ) };
                */
                PagerConfig pagerConfig = new PagerConfig(pageNo.ToInt() > 0 ? pageNo.ToInt() : 1, ConfigReader.pageSize, 0);
                int totalRecord = 0;                
                System.Data.DataSet ds = dao.GetPagedData(DbObject.SP.GET_PAGED_PRODUCTS_BY_CATEGORY, parameters, pagerConfig.PageNo, pagerConfig.PageSize, out totalRecord, true);
                pagerConfig.TotalRecord = totalRecord;                
                ViewBag.ShowEditLink = false;
                ListConfig listConfig = new ListConfig(ds.Tables[0], pagerConfig);
                ViewData[AppConstants.ViewDataKeys.SUB_MODEL] = listConfig;
            }
            return View(category);
        }
        public ActionResult GetCategories()
        {
            List<Category> entities = _Context.Categories.ToList();
            List<CategoryViewModel> categories = Mapper.Map<List<CategoryViewModel>>(entities);
            return View("~/Areas/Public/Views/Category/CategoryTree.cshtml", categories);
        }

        [HttpPost]
        public PartialViewResult GetCategoryBreadCrumb(int categoryID)
        {                           
            return PartialView("_CategoryBreadCrumb", categoryID);
        }


        [HttpPost]
        public ActionResult AddRemoveWishList(ProductViewModel product)
        {
            if (SessionCache.CurrentUser == null)
                //return View("LogOn");
                return Json(false);
            else
            {
                var wishList = _Context.UserWishLists.FirstOrDefault(P => P.UserID == SessionCache.CurrentUser.ID
                    && P.ProductID == product.ID);

                UserWishList entity = null;

                if (wishList == null)
                {
                    entity = new UserWishList();
                    _Context.AddToUserWishLists(entity);
                    entity.UserID = SessionCache.CurrentUser.ID;
                    entity.ProductID = product.ID;
                    entity.UpdatedDate = System.DateTime.Now;
                    entity.IsActive = true;

                    _Context.SaveChanges();
                }
                else
                {
                    entity = wishList;
                    entity.IsActive = (wishList.IsActive) ? false : true;
                    entity.UpdatedDate = System.DateTime.Now;

                    _Context.SaveChanges();
                }

                return Json(true);
            }
        }

        public ActionResult AddRemoveNewsLetter(string email)
        {
            var newsLetter = _Context.NewsLetters.FirstOrDefault(P => P.Email == email);

            NewsLetter entity = null;

            if (newsLetter == null)
            {
                entity = new NewsLetter();
                _Context.AddToNewsLetters(entity);
                entity.Email = email;
                entity.CreatedOn = System.DateTime.Now;
                entity.IsActive = true;

                _Context.SaveChanges();

                return Json(true);
            }
            else
                return Json(false);
            //else
            //{
            //    entity = wishList;
            //    entity.IsActive = (wishList.IsActive) ? false : true;
            //    entity.UpdatedDate = System.DateTime.Now;

            //    _Context.SaveChanges();
            //}

            
        }        

        public ActionResult Search(String key, String pageNo)
        {
            if (key.IsNullOrEmpty())
                return View(new ListConfig(null, new PagerConfig()));
            key = key.UrlDecode();
            PagerConfig pagerConfig = new PagerConfig(pageNo.ToInt() > 0 ? pageNo.ToInt() : 1, ConfigReader.SearchPageSize, 0);
            int totalRecord = 0;            
            ///Search in Lucene Index
            App.Search.ProductSearchManager searcher = new Search.ProductSearchManager();
            String productIDs = searcher.Search(key, pagerConfig.PageSize, pagerConfig.PageNo, out totalRecord);
            //String productIDs = searcher.PrefixSearch(key, pagerConfig.PageNo, pagerConfig.PageSize);
            //String productIDs = searcher.WildcardSearch(key, pagerConfig.PageNo, pagerConfig.PageSize);
            //String productIDs = searcher.AutoCompleateQuery(key, pagerConfig.PageNo, pagerConfig.PageSize);
            pagerConfig.TotalRecord = totalRecord;

            ///Get the Resulting Product Information from Database
            UtilityDAO dao = new UtilityDAO();
            DbParameter[] parameters = new[] { 
                new DbParameter("@ProductIDs", productIDs),                 
                new DbParameter("@UserID", SessionCache.CurrentUser == null ? 0 : SessionCache.CurrentUser.ID)
            };
            System.Data.DataSet ds = dao.GetDataSet(DbObject.SP.GET_PRODUCTS_BY_ID, parameters, true);            
            ListConfig listConfig = new ListConfig(ds.Tables[0], pagerConfig);
            ViewBag.SearchType = key;
            return View(listConfig);
        }

        [HttpPost]
        [ValidateInput(false)]
        public ActionResult Search(String keyword)
        {
            keyword = keyword.UrlEncode();
            return RedirectToAction("search", new { key = keyword, pageNo = 1 });
        }

        public String GetAutoCompleteSearchResult(String keyword, String maxLength)
        {
            int pageSize = maxLength.ToInt() > 0 && maxLength.ToInt() < 40 ? maxLength.ToInt() : 20; 
            ProductSearchManager searcher = new ProductSearchManager();
            List<ProductResult> result = searcher.AutoCompleateQuery(keyword, 1, pageSize);
            return result.ToJSON();
        }
        #endregion Action Methods

        #region Helper Methods

        #endregion
    }
}
